package com.apkcore.core

import android.content.Context
import android.content.pm.PackageManager
import android.util.Log
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.LifecycleOwner


//class PermissionX<T> private constructor(private val currentRequester: T) where T : LifecycleOwner {
//
//    //    private var permissionLauncher: ActivityResultLauncher<Array<String>>? = null
////    private var onPermissionsGranted: (() -> Unit)? = null
////    private var onPermissionsDenied: ((List<String>) -> Unit)? = null
//
//    companion object {
//        fun <T> with(lifecycleOwner: T): PermissionX<T> where T : LifecycleOwner {
//            if (lifecycleOwner is FragmentActivity || lifecycleOwner is Fragment) {
//                return PermissionX(lifecycleOwner)
//            } else {
//                throw IllegalArgumentException("LifecycleOwner must be an instance of FragmentActivity or Fragment")
//            }
//        }
//    }

object PermissionX {

    private lateinit var currentRequester: LifecycleOwner
    private var pers: MutableList<String> = arrayListOf()
//    private var hashset = hashSetOf<String>()

    fun with(lifecycleOwner: LifecycleOwner): PermissionX {
        if (lifecycleOwner is FragmentActivity || lifecycleOwner is Fragment) {
            this.currentRequester = lifecycleOwner
            return this
        } else {
            throw IllegalArgumentException("LifecycleOwner must be an instance of FragmentActivity or Fragment")
        }
    }

    private fun initBlankFragment(
        requester: Any,
        onPermissionsGranted: (() -> Unit)?,
        onPermissionsDenied: ((List<String>) -> Unit)?
    ): BlankFragment {
        val blankFragment = BlankFragment()
        blankFragment.setRegisterForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { granteds ->
            Log.d("bsb", "initBlankFragment: $granteds")
            handlePermissionsResult(granteds, onPermissionsGranted, onPermissionsDenied)
//            hashset.add(requester.javaClass.name)
        }
        val fragmentManager: FragmentManager = when (requester) {
            is Fragment -> {
                requester.childFragmentManager

            }

            is FragmentActivity -> {
                requester.supportFragmentManager
//                permissionLauncher = requester.registerForActivityResult(
//                    ActivityResultContracts.RequestMultiplePermissions()
//                ) { granteds: Map<String, Boolean> ->
//                    handlePermissionsResult(granteds)
//                }
            }

            else -> throw IllegalArgumentException("Requester must be Fragment or FragmentActivity")
        }
        fragmentManager.beginTransaction().add(blankFragment, "blankFragment").commitNow()
        return blankFragment
    }

    private fun handlePermissionsResult(
        granteds: Map<String, Boolean>,
        onPermissionsGranted: (() -> Unit)?,
        onPermissionsDenied: ((List<String>) -> Unit)?
    ) {
        val allGranted = granteds.all { it.value }
        if (allGranted) {
            Log.d("bsb", "handlePermissionsResult1: ")
            onPermissionsGranted?.invoke()
        } else {
            Log.d("bsb", "handlePermissionsResult2: ")
            val deniedPermissions = getDeniedPermissions(granteds)
            onPermissionsDenied?.invoke(deniedPermissions)
        }
    }

    private fun getDeniedPermissions(granteds: Map<String, Boolean>): List<String> {
        return granteds.filterValues { !it }.keys.toList()
    }

    fun permission(permission: String): PermissionX {
        pers += permission
        permission(pers)
        return this
    }

    fun permission(permissions: Array<String>): PermissionX {
        this.pers = permissions.toMutableList()
        return this
    }

    fun permission(permissions: List<String>): PermissionX {
        permission(permissions)
        return this
    }

    fun forcedRequest(
        onPermissionsDenied: ((List<String>) -> Unit)? = null,
        onPermissionsGranted: (() -> Unit)? = null,
    ) {
//        if (hashset.contains(currentRequester.javaClass.name)) {
//            hashset.remove(currentRequester.javaClass.name)
//        }
        request(onPermissionsDenied, onPermissionsGranted)
    }

    fun request(
        onPermissionsDenied: ((List<String>) -> Unit)? = null,
        onPermissionsGranted: (() -> Unit)? = null,
    ) {
//        if (hashset.contains(currentRequester.javaClass.name)) {
//            return
//        }

        // 移除多余的权限
        val context = getContext(currentRequester)
        val manifestPermissions = context.packageManager.getPackageInfo(
            context.packageName,
            PackageManager.GET_PERMISSIONS
        ).requestedPermissions
        if (manifestPermissions != null) {
            pers.retainAll(manifestPermissions.toList())
        }
        if (pers.any { !checkPermission(currentRequester, it) }) {
            val blankFragment =
                initBlankFragment(currentRequester, onPermissionsGranted, onPermissionsDenied)
            blankFragment.launch(pers.toTypedArray())
            Log.d("bsb", "request: 222")
        } else {
            onPermissionsGranted?.invoke()
            Log.d("bsb", "request: 2221111")
        }
    }

    private fun getContext(currentRequester: Any): Context {
        return when (currentRequester) {
            is Fragment -> currentRequester.requireContext()
            is FragmentActivity -> currentRequester
            else -> throw IllegalArgumentException("Requester must be Fragment or FragmentActivity")
        }
    }

    private fun checkPermission(requester: Any, permission: String): Boolean {
        val context = getContext(requester)
        return ContextCompat.checkSelfPermission(
            context,
            permission
        ) == PackageManager.PERMISSION_GRANTED
    }

    internal class BlankFragment : Fragment() {
        private var permissionLauncher: ActivityResultLauncher<Array<String>>? = null

        private var contract: ActivityResultContracts.RequestMultiplePermissions? = null
        private var callback: ActivityResultCallback<Map<String, Boolean>>? = null
        fun setRegisterForActivityResult(
            contract: ActivityResultContracts.RequestMultiplePermissions,
            callback: ActivityResultCallback<Map<String, Boolean>>
//            callback: (Map<String, Boolean>) -> Unit
        ) {
            this.contract = contract
            this.callback = callback
        }

        override fun onAttach(context: Context) {
            super.onAttach(context)
            contract?.let { contract ->
                callback?.let { callback ->
                    permissionLauncher = registerForActivityResult(contract, callback)
                }
            }
        }

        override fun onDestroyView() {
            permissionLauncher?.unregister()
//            hashset.remove(currentRequester.javaClass.name)
            super.onDestroyView()
        }

        fun launch(pers: Array<String>) {
            permissionLauncher?.launch(pers)
        }

    }
}
